package org.cst8277.ums.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.cst8277.ums.dto.UserDto;
import org.cst8277.ums.entity.User;
import org.cst8277.ums.entity.UserRole;
import org.cst8277.ums.service.IRoleService;
import org.cst8277.ums.service.IUserRoleService;
import org.cst8277.ums.service.IUserService;
import org.cst8277.ums.util.Constants;
import org.cst8277.ums.util.Md5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/ums/user")
public class UmsUserController {
    @Autowired
    private IUserService userService;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IRoleService roleService;

    @GetMapping("getUsers/{pageNum}/{pageSize}")
    public Mono<ResponseEntity<Map<String, Object>>> getUsers(@PathVariable("pageNum") Integer pageNum, @PathVariable("pageSize") Integer pageSize) {
        log.info("获取所有用户");
        Map<String, Object> response = new HashMap<>();
        Page<User> page = userService.page(new Page<User>(pageNum, pageSize));

        if (page == null || page.getTotal() == 0) {
            response.put(Constants.CODE, "500");
            response.put(Constants.MESSAGE, "Users have not been retrieved");
            response.put(Constants.DATA, new HashMap<>());
        } else {
            response.put(Constants.CODE, "200");
            response.put(Constants.MESSAGE, "List of Users has been requested successfully");
            response.put(Constants.DATA, new ArrayList<>(page.getOrders()));
        }
        return Mono.just(ResponseEntity.ok().header(Constants.CONTENT_TYPE, Constants.APPLICATION_JSON)
                .header(Constants.ACCEPT, Constants.APPLICATION_JSON).body(response));
    }

    @RequestMapping(method = RequestMethod.GET, path = "getUser/{user-id}")
    public Mono<ResponseEntity<Map<String, Object>>> getUser(@PathVariable(value = "user-id", required = true) long userId) {
        log.info("查找用户, userId:{}", userId);
        Map<String, Object> response = new HashMap<>();
        User user = userService.getById(userId);
        if (user.getId() == null) {
            response.put(Constants.CODE, "404");
            response.put(Constants.MESSAGE, "User have not been found");
            response.put(Constants.DATA, new User());
        } else {
            response.put(Constants.CODE, "200");
            response.put(Constants.MESSAGE, "User has been retrieved successfully");
            response.put(Constants.DATA, user);
        }
        return Mono.just(ResponseEntity.ok().header(Constants.CONTENT_TYPE, Constants.APPLICATION_JSON)
                .header(Constants.ACCEPT, Constants.APPLICATION_JSON).body(response));
    }

    @RequestMapping(method = RequestMethod.POST, path = "/addUser/user", consumes = Constants.APPLICATION_JSON)
    public Mono<ResponseEntity<Map<String, Object>>> createUser(@RequestBody User user) {
        Map<String, Object> response = new HashMap<>();
        log.info("开始创建用户, user:{}", user);
        user.setUpdateTime(new Date());
        user.setCreateTime(new Date());
        String newPasswd = Md5Util.md5sum(user.getPassword());
        user.setPassword(newPasswd);
        user.setUpdator(Constants.DEFAULT_UPDATOR);

        boolean result = userService.save(user);
        if (result == false) {
            response.put(Constants.CODE, "500");
            response.put(Constants.MESSAGE, "User has not been created");
            response.put(Constants.DATA, "Check email for duplicates first");
        } else {
            response.put(Constants.CODE, "201");
            response.put(Constants.MESSAGE, "User created");
            response.put(Constants.DATA, user.getId());
        }
        return Mono.just(ResponseEntity.ok().header(Constants.CONTENT_TYPE, Constants.APPLICATION_JSON)
                .header(Constants.ACCEPT, Constants.APPLICATION_JSON).body(response));
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "deleteUser/{user-id}")
    public Mono<ResponseEntity<Map<String, Object>>> deleteUser(@PathVariable(value = "user-id", required = true) long userId) {
        log.info("开始删除用户, userId:{}", userId);
        Map<String, Object> response = new HashMap<>();
        boolean result = userService.removeById(userId);
        if (result == false) {
            response.put(Constants.CODE, "500");
            response.put(Constants.MESSAGE, "Error happened while deleting user");
            response.put(Constants.DATA, userId);
        } else {
            response.put(Constants.CODE, "200");
            response.put(Constants.MESSAGE, "User deleted");
            response.put(Constants.DATA, userId);
        }
        return Mono.just(ResponseEntity.ok().header(Constants.CONTENT_TYPE, Constants.APPLICATION_JSON)
                .header(Constants.ACCEPT, Constants.APPLICATION_JSON).body(response));
    }

    @RequestMapping(method = RequestMethod.GET, path = "getUserInfo/{user-id}")
    public Mono<ResponseEntity<Map<String, Object>>> getUserInfo(@PathVariable(value = "user-id", required = true) long userId) {
        log.info("查找用户, userId:{}", userId);
        Map<String, Object> response = new HashMap<>();
        User user = userService.getById(userId);
        UserDto userDto = new UserDto();
        if (user.getId() == null) {
            response.put(Constants.CODE, "404");
            response.put(Constants.MESSAGE, "User have not been found");
            response.put(Constants.DATA, new UserDto());
        } else {
            UserRole userRole = userRoleService.getByUserId(user.getId());
            userDto.setId(user.getId());
            userDto.setEmail(user.getEmail());
            userDto.setUsername(user.getUsername());
            if (userRole != null) {
                userDto.setRoleName(userRole.getRoleName());
            }
            response.put(Constants.CODE, "200");
            response.put(Constants.MESSAGE, "User has been retrieved successfully");
            response.put(Constants.DATA, userDto);
        }
        return Mono.just(ResponseEntity.ok().header(Constants.CONTENT_TYPE, Constants.APPLICATION_JSON)
                .header(Constants.ACCEPT, Constants.APPLICATION_JSON).body(response));
    }
}